package com.cgs.mongo.delegate;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.mongodb.Block;
import com.mongodb.CursorType;
import com.mongodb.Function;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoIterable;
import com.mongodb.client.model.Collation;
import com.mongodb.lang.Nullable;
import org.bson.Document;
import org.bson.conversions.Bson;

import java.util.Collection;
import java.util.Map;
import java.util.Spliterator;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import static com.cgs.mongo.utils.WrapperUtils.*;
import static com.cgs.mongo.utils.WrapperUtils.asBsonDocument;

public class FindIterableWrapper<TDocument> implements FindIterable<TDocument> {

    private FindIterable<TDocument> delegate;

    public FindIterableWrapper(FindIterable<TDocument> delegate) {
        this.delegate = delegate;
    }

    public FindIterable<TDocument> filter(Map<String, Object> filter) throws JsonProcessingException {
        return delegate.filter(asBsonDocument(filter));
    }

    @Override
    public FindIterable<TDocument> filter(Bson filter) {
        return delegate.filter(filter);
    }

    @Override
    public FindIterable<TDocument> limit(int limit) {
        return delegate.limit(limit);
    }

    @Override
    public FindIterable<TDocument> skip(int skip) {
        return delegate.skip(skip);
    }

    @Override
    public FindIterable<TDocument> maxTime(long maxTime, TimeUnit timeUnit) {
        return delegate.maxTime(maxTime, timeUnit);
    }

    @Override
    public FindIterable<TDocument> maxAwaitTime(long maxAwaitTime, TimeUnit timeUnit) {
        return delegate.maxAwaitTime(maxAwaitTime, timeUnit);
    }

    @Override
    public FindIterable<TDocument> modifiers(Bson modifiers) {
        return delegate.modifiers(modifiers);
    }

    public FindIterable<TDocument> maxTimeSeconds(long maxTime) {
        return delegate.maxTime(maxTime, TimeUnit.SECONDS);
    }

    public FindIterable<TDocument> maxAwaitTimeSeconds(long maxAwaitTime) {
        return delegate.maxAwaitTime(maxAwaitTime, TimeUnit.SECONDS);
    }

    public FindIterable<TDocument> projection(Map<String, Object> projection) throws JsonProcessingException {
        return delegate.projection(asBsonDocument(projection));
    }

    @Override
    public FindIterable<TDocument> projection(Bson projection) {
        return delegate.projection(projection);
    }

    public FindIterable<TDocument> sort(Map<String, Object> sort) throws JsonProcessingException {
        return delegate.sort(asBsonDocument(sort));
    }

    @Override
    public FindIterable<TDocument> sort(Bson sort) {
        return delegate.sort(sort);
    }

    @Override
    public FindIterable<TDocument> noCursorTimeout(boolean noCursorTimeout) {
        return delegate.noCursorTimeout(noCursorTimeout);
    }

    @Override
    public FindIterable<TDocument> oplogReplay(boolean oplogReplay) {
        return delegate.oplogReplay(oplogReplay);
    }

    @Override
    public FindIterable<TDocument> partial(boolean partial) {
        return delegate.partial(partial);
    }

    @Override
    public FindIterable<TDocument> cursorType(CursorType cursorType) {
        return null;
    }

    public FindIterable<TDocument> cursorType(String cursorType) {
        return delegate.cursorType(CursorType.valueOf(cursorType));
    }

    @Override
    public FindIterable<TDocument> batchSize(int batchSize) {
        return delegate.batchSize(batchSize);
    }

    @Override
    public FindIterable<TDocument> collation(Collation collation) {
        return null;
    }

    @Override
    public FindIterable<TDocument> comment(String comment) {
        return delegate.comment(comment);
    }


    public FindIterable<TDocument> hint(Map<String, Object> hint) throws JsonProcessingException {
        return delegate.hint(asBsonDocument(hint));
    }

    @Override
    public FindIterable<TDocument> hint(Bson hint) {
        return delegate.hint(hint);
    }

    public FindIterable<TDocument> max(Map<String, Object> max) throws JsonProcessingException {
        return delegate.max(asBsonDocument(max));
    }

    @Override
    public FindIterable<TDocument> max(Bson max) {
        return delegate.max(max);
    }

    @Override
    public FindIterable<TDocument> min(Bson min) {
        return delegate.min(min);
    }

    @Override
    public FindIterable<TDocument> maxScan(long maxScan) {
        return null;
    }

    @Override
    public FindIterable<TDocument> returnKey(boolean returnKey) {
        return delegate.returnKey(returnKey);
    }

    @Override
    public FindIterable<TDocument> showRecordId(boolean showRecordId) {
        return delegate.showRecordId(showRecordId);
    }

    @Override
    public FindIterable<TDocument> snapshot(boolean snapshot) {
        return delegate.snapshot(snapshot);
    }

    @Override
    public MongoCursor<TDocument> iterator() {
        return delegate.iterator();
    }

    @Nullable
    @Override
    public TDocument first() {
        return delegate.first();
    }

    @Override
    public <U> MongoIterable<U> map(Function<TDocument, U> mapper) {
        return delegate.map(mapper);
    }

    @Override
    public void forEach(Block<? super TDocument> block) {
        delegate.forEach(block);
    }

    @Override
    public <A extends Collection<? super TDocument>> A into(A target) {
        return delegate.into(target);
    }

    @Override
    public void forEach(Consumer<? super TDocument> action) {
        delegate.forEach(action);
    }

    @Override
    public Spliterator<TDocument> spliterator() {
        return delegate.spliterator();
    }


}
